package handler

import (
	"context"
	"encoding/json"
	"github.com/apache/rocketmq-client-go/v2/consumer"
	"github.com/apache/rocketmq-client-go/v2/primitive"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"sale_system/inventory_srv/global"
	"sale_system/inventory_srv/model"
)

type OrderInfo struct {
	OrderSn string
}

// AutoReBack 消息队列自动归还库存
func AutoReBack(ctx context.Context, msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
	// 通过消息队列，获取到库存归还的半消息，然后进行库存归还
	// 归还库存，我们需要知道具体归还多少？但是我们如何解决重复归还问题，需要解决幂等性
	// 所以我们构建一张订单表，用来记录订单扣减的数据表

	zap.S().Info("进行库存归还")

	for i := range msgs { // 一条信息对应一张订单
		var orderInfo OrderInfo
		err := json.Unmarshal(msgs[i].Body, &orderInfo) // 截取到对应的OrderSn
		if err != nil {
			zap.S().Info("解析json失败，msg: %v\n", msgs[i].Body)
			return consumer.ConsumeSuccess, nil // 无法解析数据，进行消息丢弃
		}

		// 读取sellDetail通过这里获得的OrderSn进行库存归还，并将status设置为2已归还状态
		tx := global.DB.Begin()
		var sellDetail model.StockSellDetail
		// 必须是存在这个订单号，并且状态为已扣减，我们才进行归还
		result := tx.Where(model.StockSellDetail{OrderSn: orderInfo.OrderSn, Status: 1}).First(&sellDetail) // 需不需要加model？
		if result.RowsAffected == 0 {
			return consumer.ConsumeSuccess, nil // 表示没有记录已归还
		}

		// 进行商品库存归还
		for _, good := range sellDetail.Detail {
			result = tx.Model(&model.Inventory{}).Where(&model.Inventory{Goods: good.Goods}).Update("stocks", gorm.Expr("stocks+?", good.Num))
			if result.RowsAffected == 0 {
				tx.Rollback()
				return consumer.ConsumeRetryLater, nil
			}
		}
		sellDetail.Status = 2
		result = tx.Save(&sellDetail)
		if result.RowsAffected == 0 {
			tx.Rollback()
			return consumer.ConsumeRetryLater, nil
		}
		tx.Commit()
	}

	return consumer.ConsumeSuccess, nil
}
